﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace canvasTest
{
    public partial class MainWindow : Window
    {
        // 原有字段
        private const int Rows = 10;
        private const int Cols = 10;
        private const double BlockWidth = 256;
        private const double BlockHeight = 65;
        private const double Spacing = 0;
        private const double ZoomSpeed = 0.1;
        private const double MinZoom = 0.1;
        private const double MaxZoom = 150.0;
        private readonly Random _random = new Random();
        private Point _dragOffset;
        private BlockDesign _draggedBlock;
        private double _currentScale = 1.0;

        // 新增连接相关字段
        private BlockDesign _currentSourceBlock;
        private Connection _currentConnection;
        private readonly List<Connection> _connections = new List<Connection>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeBlocks();
            UpdateCanvasSize();
        }

        private void InitializeBlocks()
        {
            for (var i = 0; i < Rows; i++)
            {
                for (var j = 0; j < Cols; j++)
                {
                    var block = CreateBlock(i, j);
                    block.ConnectorClicked += Block_ConnectorClicked; // 订阅连接点事件
                    MainCanvas.Children.Add(block);
                }
            }
        }

        private BlockDesign CreateBlock(int row, int col)
        {
            var block = new BlockDesign
            {
                Fill = new SolidColorBrush(GenerateRandomColor()),
                Stroke = Brushes.Black,
                StrokeThickness = 0.5
            };

            Canvas.SetLeft(block, col * (BlockWidth + Spacing));
            Canvas.SetTop(block, row * (BlockHeight + Spacing));

            block.MouseDown += Block_MouseDown;
            block.MouseMove += Block_MouseMove;
            block.MouseUp += Block_MouseUp;

            return block;
        }

        #region 连接逻辑
        private void Block_ConnectorClicked(object sender, MouseButtonEventArgs e)
        {
            if (e is BlockConnectorEventArgs args)
            {
                var block = (BlockDesign)sender;

                if (args.IsOutput) // 开始新连接
                {
                    StartNewConnection(block);
                }
                else // 完成现有连接
                {
                    CompleteConnection(block);
                }
            }
        }

        private void StartNewConnection(BlockDesign sourceBlock)
        {
            _currentSourceBlock = sourceBlock;
            _currentConnection = new Connection
            {
                SourceBlock = sourceBlock,
                StartPoint = sourceBlock.OutputConnectorPosition,
                EndPoint = sourceBlock.OutputConnectorPosition
            };

            MainCanvas.Children.Add(_currentConnection);
            Panel.SetZIndex(_currentConnection, -1);
            MainCanvas.MouseMove += OnConnectionDragging;
            MainCanvas.MouseUp += OnConnectionReleased;
        }

        private void OnConnectionDragging(object sender, MouseEventArgs e)
        {
            if (_currentConnection != null)
            {
                _currentConnection.EndPoint = e.GetPosition(MainCanvas);
            }
        }

        private void CompleteConnection(BlockDesign targetBlock)
        {
            if (_currentSourceBlock == null ||
                _currentConnection == null ||
                _currentSourceBlock == targetBlock) return;

            _currentConnection.TargetBlock = targetBlock;
            _currentConnection.UpdateConnection();
            _connections.Add(_currentConnection);

            CleanupConnection();
        }

        private void OnConnectionReleased(object sender, MouseButtonEventArgs e)
        {
            CleanupConnection();
        }

        private void CleanupConnection()
        {
            if (_currentConnection == null) return;

            MainCanvas.MouseMove -= OnConnectionDragging;
            MainCanvas.MouseUp -= OnConnectionReleased;

            if (_currentConnection.TargetBlock == null)
            {
                MainCanvas.Children.Remove(_currentConnection);
            }

            _currentConnection = null;
            _currentSourceBlock = null;
        }

        private void UpdateConnections(BlockDesign movedBlock)
        {
            foreach (var connection in _connections)
            {
                if (connection.SourceBlock == movedBlock ||
                    connection.TargetBlock == movedBlock)
                {
                    connection.UpdateConnection();
                }
            }
        }
        #endregion

        #region 原有方法（需小修改）
        private Color GenerateRandomColor()
        {
            return Color.FromRgb(
                (byte)_random.Next(200, 256),
                (byte)_random.Next(200, 256),
                (byte)_random.Next(200, 256));
        }

        private void UpdateCanvasSize()
        {
            var maxRight = MainCanvas.Children.OfType<BlockDesign>()
                .Max(block => Canvas.GetLeft(block) + block.ActualWidth);

            var maxBottom = MainCanvas.Children.OfType<BlockDesign>()
                .Max(block => Canvas.GetTop(block) + block.ActualHeight);

            MainCanvas.Width = maxRight + Spacing;
            MainCanvas.Height = maxBottom + Spacing;
        }

        private void Block_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (sender is BlockDesign block)
            {
                _draggedBlock = block;
                var mousePos = e.GetPosition(MainCanvas);
                _dragOffset = new Point(
                    mousePos.X - Canvas.GetLeft(block),
                    mousePos.Y - Canvas.GetTop(block));

                Panel.SetZIndex(block, 100);
                block.Opacity = 0.8;
                block.Stroke = Brushes.Red;
                block.CaptureMouse();
            }
        }

        private void Block_MouseMove(object sender, MouseEventArgs e)
        {
            if (_draggedBlock == null || e.LeftButton != MouseButtonState.Pressed) return;

            var mousePos = e.GetPosition(MainCanvas);
            Canvas.SetLeft(_draggedBlock, mousePos.X - _dragOffset.X);
            Canvas.SetTop(_draggedBlock, mousePos.Y - _dragOffset.Y);

            UpdateConnections(_draggedBlock); // 新增：移动时更新连线
        }

        private void Block_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (_draggedBlock == null) return;

            _draggedBlock.ReleaseMouseCapture();
            _draggedBlock.Opacity = 1.0;
            _draggedBlock.Stroke = Brushes.Black;
            Panel.SetZIndex(_draggedBlock, 0);
            _draggedBlock = null;

            UpdateCanvasSize();
        }

        private void MainScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (Keyboard.Modifiers != ModifierKeys.Control) return;

            var zoomCenter = e.GetPosition(MainScrollViewer);
            var contentPosition = MainScrollViewer.TranslatePoint(zoomCenter, MainCanvas);

            ApplyZoom(e.Delta > 0 ? ZoomSpeed : -ZoomSpeed);
            AdjustScrollPosition(contentPosition, zoomCenter);

            e.Handled = true;
        }

        private void ApplyZoom(double delta)
        {
            _currentScale = Math.Max(MinZoom, Math.Min(MaxZoom, _currentScale * (1 + delta)));
            CanvasScaleTransform.ScaleX = _currentScale;
            CanvasScaleTransform.ScaleY = _currentScale;

            // 缩放时更新所有连线
            foreach (var connection in _connections)
            {
                connection.UpdateConnection();
            }
        }

        private void AdjustScrollPosition(Point contentPosition, Point viewportPoint)
        {
            var newHorizontal = contentPosition.X * _currentScale - viewportPoint.X;
            var newVertical = contentPosition.Y * _currentScale - viewportPoint.Y;

            MainScrollViewer.ScrollToHorizontalOffset(newHorizontal);
            MainScrollViewer.ScrollToVerticalOffset(newVertical);
        }
        #endregion
    }
}